import axios, { InternalAxiosRequestConfig, AxiosResponse, Method } from 'axios';
import { IR } from '@/types/response';
import createPinia from '@/pinia';
import { userStore } from '@/pinia/userStore';
import { error } from './message';
const userstore = userStore(createPinia);

const responseType = "json";//返回类型
const timeoutPeriod = 1500;// 超时时间
const timeout = 5;//最多超时五次



const newAxios = axios.create({
  // baseURL: "http://localhost:5173/api/",
  baseURL: import.meta.env.VITE_API_URL,
  timeout: 5000,
  responseType: 'json',
})
// 请求拦截器
newAxios.interceptors.request.use(async (config: InternalAxiosRequestConfig<any>) => {
  const { authorize } = config.headers;
  if (authorize) {
    if (userstore.token) {
      config.headers.authorize = userstore.token;
    } else {
      userstore.setToken("token", "")
      userstore.setLoginStatus(false)
      return Promise.reject("token is null");
    }

  }

  return config;
}, error => {
  return Promise.reject(error)
});

// 响应拦截器
newAxios.interceptors.response.use((config: AxiosResponse) => {

  return config;
}, (err) => {
  if (err.code == "ECONNABORTED") {//超时异常
    error("请求超时")
    return sendTimeOut(err.config.headers, err.config)
  }
  error(err)
  return Promise.reject(err);

})
/**
 * 
 * @param url 请求路径
 * @param method  请求类型
 * @param options 配置
 * @returns config
 */
export const request = <T>(url: string, method: Method, options: { [property: string]: any } = {}, signal?: AbortSignal) => {
  options.timeout = timeout;
  const res = newAxios<IR<T>>({
    url,//路径
    data: options.body ?? {},
    method,//请求方式
    responseType,
    headers: options,
    signal
  })
  return res.then(res => res.data);
}

/**
 * 超时方法
 * @param headers 请求头
 * @param  config 当前请求的所有配置属性
 */
function sendTimeOut(headers: { [property: string]: any }, config: AxiosResponse) {
  // 判断是否存在该字段
  headers.timeout--;
  if (headers.timeout && headers.timeout > 0) {
    //拼接请求
    const res = new Promise(resolve => {
      setTimeout(() => {
        resolve(newAxios(config))
      }, timeoutPeriod)
    })
    return res.then(res => res)
  }
}

/**
 * 并发请求
 * @param fn 函数 
 * @param size 并发数量
 * @returns 数组
 */
export function concurrencyRequest(fn: Function[], size: number = 1) {
  return new Promise(async (resolve) => {
    if (fn.length <= 0) {
      resolve([])
    }
    size = Math.min(fn.length, size)
    //@ts-ignore
    let arr = [];
    let count = 0;
    let index = 0;

    function r() {
      if (index >= fn.length) return;
      const f = fn[index];
      let i = index;
      index++;
      f().then((res: IR<any>) => {
        try {
          arr[i] = res.data;
        } finally {
          count++;
          r()
          if (count == fn.length) {
            //@ts-ignore
            resolve(arr)
          }
        }
      })
    }

    for (let i = 0; i < size; i++) {
      r()
    }

  })
}


export default newAxios;